"""
##########################
#      classs_tools      #
#  coding by XCreeperPa  #
##########################

***依赖***
    无

***架构***
    ==ClassSet==
    --类集合--
        class：
            ==ObjectReturn==
            --返回的对象--
                __init__(self, obj, CS, cls_now) 初始化
                __setattr__(self, key, value) 设置属性
                __getattr__(self, item) 获取属性

        methods：
            __init__(self) 初始化
            __getattr__(self, item) 获取属性
            __setattr__(self, key, value) 设置属性
            __call__(self, *args, **kwargs) 调用对象
            add(self, new_cls, method: dict) 增加类
            add_method(self) 增加类的方法 未完成
            change_cls(self, cls) 改变当前使用的类

***使用方法***
    1.新建类集合 例如：ClassSet()
    2.往类集合里增加类，并绑定方法 例如：ClassSetObject.add(a_class, {new_method_name:method_object})
    3.用类集合对象实例化对象 例如： ClassSetObject(*args, **kwargs)
    4.使用类集合对象实例化出来的对象，使用方法和直接用类实例化对象效果一致

***测试***
    详见文件末尾  if __name__ == '__main__'  代码块

====end====
"""


# 类集合
class ClassSet:
    # 返回的对象
    class ObjectReturn:
        # 初始化
        def __init__(self, obj, CS, cls_now):
            self.__dict__['obj'] = obj
            self.cls_now = cls_now
            self.CS = CS

        # 设置属性
        def __setattr__(self, key, value):
            self.__dict__[key] = value

        # 获取属性
        def __getattr__(self, item):
            if item in self.__dict__['obj'].__dict__.keys():
                return self.__dict__['obj'].__dict__[item]
            else:
                return lambda *args, **kwargs: self.__dict__['CS'].__dict__['methods'][item][self.cls_now](self=self,
                                                                                                           *args,
                                                                                                           **kwargs)

    # 初始化
    def __init__(self):
        self.__dict__['cls_now'] = None
        self.__dict__['cls'] = list()
        self.__dict__['methods'] = dict()

    # 获取属性
    def __getattr__(self, item):
        return self.__dict__[self.methods[item][self.__dict__['cls_now']]]

    # 设置属性
    def __setattr__(self, key, value):
        self.__dict__[self.methods[key]] = value

    # 调用对象
    def __call__(self, *args, **kwargs):
        # return self.cls_now(*args, **kwargs)
        return self.ObjectReturn(self.cls_now(*args, **kwargs), self, self.cls_now)

    # 增加类
    def add(self, new_cls, method: dict):
        if isinstance(new_cls, type):
            self.cls.append(new_cls)
            for i, j in method.items():
                try:
                    self.methods[i]
                except KeyError:
                    self.methods[i] = dict()
                self.__dict__['cls_now'] = new_cls
                self.methods[i][self.__dict__['cls_now']] = j
                self.__dict__['cls_now'] = new_cls
        else:
            raise TypeError('Must be of new_cls new_cls!')

    # 增加类的方法 未完成
    def add_method(self):
        pass

    # 改变当前使用的类
    def change_cls(self, cls):
        self.__dict__['cls_now'] = self.__dict__['cls'][self.__dict__['cls'].index(cls)]


if __name__ == '__main__':
    """
    classes_tools测试
    测试用例：
    第一组：A1、A2
    第二组：B1、B2
    """
    # # # # 测试用例（类）生成# # # #
    class A1:
        def __init__(self, n1, n2):
            print('class A1 init')
            self.n1 = n1
            self.n2 = n2

        def Sum(self):
            return self.n1 + self.n2


    class A2:
        def __init__(self, n1, n2):
            print('class A2 init')
            self.sum_value = n1 + n2

        def sum(self):
            return self.sum_value


    class B1:
        def __init__(self, a_str):
            print('class B1 init')
            self.a_str = a_str

        def int(self):
            return int(self.a_str)


    class B2:
        def __init__(self, a_str):
            print('class B2 init')
            self.number = int(a_str)

        def __int__(self):
            return self.number


    # # # # 第一组测试 # # # #
    CSA = ClassSet()  # 生成类集合对象
    # 增加类到类集合
    CSA.add(new_cls=A1, method={'sum': A1.Sum})
    CSA.add(new_cls=A2, method={'sum': A2.sum})

    CSA.change_cls(A1)  # 调整使用的类
    test = CSA(1, 2)  # 尝试使用类集合对象生成对象
    print("尝试通过test对象的sum方法调用A1类的Sum方法：", test.sum())  # 尝试调用类集合生成的对象的方法

    CSA.change_cls(A2)  # 调整使用的类
    test2 = CSA(1, 2)  # 尝试使用类集合对象生成对象
    print("尝试通过test2对象的sum方法调用A2类的sum方法：", test2.sum())  # 尝试调用类集合生成的对象的方法

    # # # # 第二组测试 # # # #
    CSB = ClassSet()  # 生成类集合对象
    # 增加类到类集合
    CSB.add(new_cls=B1, method={'int': B1.int})
    CSB.add(new_cls=B2, method={'int': B2.__int__})

    CSB.change_cls(B1)  # 调整使用的类
    test3 = CSB(100)  # 尝试使用类集合对象生成对象
    print("尝试通过test3对象的int方法调用B1类的int方法：", test3.int())  # 尝试调用类集合生成的对象的方法

    CSB.change_cls(B2)  # 调整使用的类
    test4 = CSB(100)  # 尝试使用类集合对象生成对象
    print("尝试通过test4对象的int方法调用B2类的__int__方法：", test4.int())  # 尝试调用类集合生成的对象的方法
